-
Notifications
You must be signed in to change notification settings - Fork 13.3k
LeakSanitizer, ThreadSanitizer, AddressSanitizer and MemorySanitizer support #38699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @nikomatsakis (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
This is WIP revival of #31605. Right now, this only contains the Leak Sanitizer I'm bringing this back to life because one concern brought up in the original PR Comments
Concerns
TODO
|
@@ -23,6 +23,9 @@ compiler_builtins = { path = "../libcompiler_builtins" } | |||
std_unicode = { path = "../libstd_unicode" } | |||
unwind = { path = "../libunwind" } | |||
|
|||
[target.x86_64-unknown-linux-gnu.dependencies] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also a hack to place the rustc_lsan
crate in the sysroot. (because std
doesn't actually depend on rustc_lsan
)
@@ -0,0 +1,6 @@ | |||
#![cfg_attr(not(stage0), feature(sanitizer_runtime))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose this crate should also contain the -lpthread -lrt -lm
linker flags that runtimes supossedly depend on. But I'm not sure what runtime depends on what library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh that's ok b/c they're all pulled in through libstd anyway
☔ The latest upstream changes (presumably #38697) made this pull request unmergeable. Please resolve the merge conflicts. |
@japaric I'm excited to hear that xargo can compile std with custom flags. However, I feel like there is an RFC wanting to be written here. But I'm not quite sure what it is. =) At minimum, surely a feature gate of some kind would be required. |
Neat! How come we need to specially recognize the asan crate? Does it need to go in a special place on the linker command line? I'm not really sure what the best way to expose this will be long-term. For now, though, having it be optional and behind a feature gate seems ok. |
(a) It needs to be linked using |
I think the ordering is guaranteed via |
@alexcrichton That is, indeed, the case. It doesn't work without |
Travis failure seems legit to me: "llvm-config not found". |
OK. Added ThreadSanitizer support and added an unstable Using LeakSanitizer is as simple as (*) Actually, first you have patch --- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -7,7 +7,6 @@ build = "build.rs"
[lib]
name = "std"
path = "lib.rs"
-crate-type = ["dylib", "rlib"]
[dependencies]
alloc = { path = "../liballoc" } Some comments: LeakSanitizer only requires linking a runtime so, IMO, it makes sense to ThreadSanitizer requires recompiling the rust-lang/compiler-rt needs to be patched to make tsan work with PIE |
src/librustc_llvm/lib.rs
Outdated
@@ -432,3 +432,4 @@ impl Drop for OperandBundleDef { | |||
mod llvmdeps { | |||
include! { env!("CFG_LLVM_LINKAGE_FILE") } | |||
} | |||
#[link(name = "ffi")] extern {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO remove. (Sometimes I forget to not commit this -- workaround for #34486)
Pushed AddressSanitizer support and added an example to the PR description. Interestingly, an empty
|
travis says:
not sure what's up w/ that |
Quoting myself
Travis is testing on Ubuntu. We should build MemorySanitizer is now working (example in the PR description) but requires the latest compiler-rt release. We could backport some stuff to make our fork work (but we would have to first figure out what needs to be backported) or we could simply upgrade our fork to something more recent (easier). |
So, @alexcrichton -- I feel more-or-less about experimenting in this direction without an RFC, but it seems like we should have some docs. Maybe a tracking issue? I feel like I would not want this interface to stabilize without an RFC. Not sure what team has jurisdiction here, probably @rust-lang/compiler or @rust-lang/tools. |
Yeah I'm fine experimenting here as well. I want to make sure that everything is thoroughly feature gated, but beyond that it seems worthwhile to enable supporting this at all |
I wonder though if we can experiment here with less of this support in-tree. @japaric do you have an idea of how we might minimize basically the size of this PR? Ideally we wouldn't maintain all of this in tree because development would be slowed down, and hopefully one day these crates can all be on crates.io anyway. I'm slightly hesitant here as this would be one of the first "linux only" features we support in-tree, so if we can keep it external that would be nice. |
src/librustc_trans/back/link.rs
Outdated
// We must link the sanitizer runtime using -Wl,--whole-archive but since | ||
// it's packed in a .rlib, it contains stuff that are not objects that will | ||
// make the linker error. So we must remove those bits from the .rlib before | ||
// linking it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it need --whole-archive
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the dependency graph (the sanitizer runtime gets injected as a direct dependency of the "top" crate) the runtime rlib ends up being one of the first linker arguments. Because linkers are lazy, if we don't use whole-archive, the linker will end up dropping most / all of the symbols in it (because the preceding linker argument didn't directly need the symbols). whole-archive prevents that; it forces the linker to keep all the symbols around as it keeps looking at the next linker arguments.
@alexcrichton Initial testing with rustc_lsan shows that the sanitizer runtimes can live out of tree. I'll update the PR with that in mind. |
Great work, @japaric! Some thoughts on integration into the compiler:
|
@japaric It is great to see more work on sanitizer support! Regarding the question how much of this should be in-tree or not, I think the |
@bors r=alexcrichton |
📌 Commit e180dd5 has been approved by |
Should this be marked with relnotes tag? |
@alexcrichton Done. #39699 |
Thanks, @japaric , what a great feature! |
@japaric @alexcrichton This PR integrates with rustbuild in a really weird way. It adds some always-enabled 'optional' std features, lsan/msan/asan, and then omits actually producing any code for them if the LLVM_CONFIG environment variable is absent; the LLVM_CONFIG variable is only added if --enable-sanitizers is passed. Shouldn't there be more sanity in this? Actually enabling the feature only if the config flag is on? |
@whitequark sounds reasonable to me, yeah. We may also be able to remove the features now as they were from a previous iteration as well. @japaric what do you think? |
Yeah, seems fine to remove the Cargo features. I'll prepare a PR. |
Examples
LeakSanitizer
ThreadSanitizer
AddressSanitizer
MemorySanitizer